package com.qire.antscore.entity;

import com.qire.antscore.common.AssertUtils;
import com.qire.antscore.common.DeepLinkUtils;

import java.util.ArrayList;
import java.util.List;

import javax.lang.model.element.Element;

public class DeepLinkMeta {

    public enum DeepLinkType {
        Page,
        Action;
    }

    /**
     * 注解使用的类对象
     */
    public final Element element;

    public final DeepLinkType linkType;

    private String scheme;

    private String host;

    public final List<String> pathSegmentList = new ArrayList<>();

    public DeepLinkMeta(Element element, DeepLinkType linkType) {
        this.element = element;
        this.linkType = linkType;
    }

    public String fullPathUseToMatch() {
        return AssertUtils.notEmpty(host()) ? "/" + host() + fullPath() : fullPath();
    }

    public String scheme() {
        return scheme;
    }

    public String host() {
        return host;
    }

    public String fullPath() {
        StringBuilder pathBuilder = new StringBuilder();
        for(String pathSegment : pathSegmentList) {
            pathBuilder.append("/").append(pathSegment);
        }

        return pathBuilder.toString();
    }

    @Override
    public String toString() {
        StringBuilder pathBuilder = new StringBuilder();
        for(String path : pathSegmentList) {
            pathBuilder.append(path).append(",");
        }

        return String.format("element: %s, scheme: %s, host: %s, pathSegments: %s", element.getSimpleName(), scheme, host, pathBuilder);
    }

    /**
     * 构建 DeepLinkMeta 通过解析 urlPath
     * @param element 目标元素
     * @param linkType 连接行为类型
     * @param path urlPath
     * @return
     */
    public static DeepLinkMeta parsePath(Element element, DeepLinkType linkType, String path) {

        // 构建 DeepLinkMeta
        DeepLinkMeta meta = new DeepLinkMeta(element, linkType);

        /////////////////////////////开始解析地址/////////////////////////////////////
        int pos = DeepLinkUtils.skipLeadingAsciiWhitespace(path, 0, path.length());
        int limit = DeepLinkUtils.skipTrailingAsciiWhitespace(path, pos, path.length());

        // Scheme. 协议
        int schemeDelimiterOffset = DeepLinkUtils.schemeDelimiterOffset(path, pos, limit);
        if (schemeDelimiterOffset != -1) {
            if (path.regionMatches(true, pos, "https:", 0, 6)) {
                meta.scheme = "https";
                pos += "https:".length();
            } else if (path.regionMatches(true, pos, "http:", 0, 5)) {
                meta.scheme = "http";
                pos += "http:".length();
            } else {
                meta.scheme = path.substring(pos, schemeDelimiterOffset);
                pos += meta.scheme.length() + 1;
            }
        }

        // Authority.
        /**
         * path 以2个或更多斜杠开头,则适用
         * authority 结构为 ：username:password@host:port
         * username，password 和 port 是可选的，目前暂不处理这三个，只关注 host
         */
        int slashCount = DeepLinkUtils.slashCount(path, pos, limit);
        if (slashCount >= 2) {
            pos += slashCount;
            authority:
            while (true) {
                int componentDelimiterOffset = DeepLinkUtils.delimiterOffset(path, pos, limit, "@/\\?#");
                int c = componentDelimiterOffset != limit ? path.charAt(componentDelimiterOffset) : -1;
                switch (c) {
                    case '@':
                        // User info 处理.
                        // 暂未实现，目前未使用带以后有需求再完成
                        pos = componentDelimiterOffset + 1;
                        break;

                    case -1:
                    case '/':
                    case '\\':
                    case '?':
                    case '#':
                        // Host info 处理.
                        int portColonOffset = DeepLinkUtils.portColonOffset(path, pos, componentDelimiterOffset);
                        if (portColonOffset + 1 < componentDelimiterOffset) {
                            meta.host = DeepLinkUtils.canonicalizeHost(path, pos, portColonOffset);
                        } else {
                            meta.host = DeepLinkUtils.canonicalizeHost(path, pos, portColonOffset);
                        }
                        pos = componentDelimiterOffset;
                        break authority;
                    default:
                        break;
                }
            }
        }

        // relative path. 地址
        int pathDelimiterOffset = DeepLinkUtils.delimiterOffset(path, pos, limit, "?#");
        DeepLinkUtils.resolvePath(meta.pathSegmentList, path, pos, pathDelimiterOffset);
        pos = pathDelimiterOffset;

        return meta;
    }

}
